WORKERS AHEAD!
You are viewing the development documentation for the Apereo CAS server. The functionality presented here is not officially released yet. This is a work in progress and will be continually updated as development moves forward. You are most encouraged to test the changes presented.
Apache Tomcat - Embedded Servlet Container Configuration
Note that by default, the embedded container attempts to enable the HTTP2 protocol.
1
2
3
4
5
<dependency>
<groupId>org.apereo.cas</groupId>
<artifactId>cas-server-webapp-tomcat</artifactId>
<version>${cas.version}</version>
</dependency>
1
implementation "org.apereo.cas:cas-server-webapp-tomcat:${project.'cas.version'}"
1
2
3
4
5
6
7
8
9
dependencyManagement {
imports {
mavenBom "org.apereo.cas:cas-server-support-bom:${project.'cas.version'}"
}
}
dependencies {
implementation "org.apereo.cas:cas-server-webapp-tomcat"
}
IPv4 Configuration
In order to force Apache Tomcat to use IPv4, configure the following as a system property for your run command:
1
-Djava.net.preferIPv4Stack=true
The same sort of configuration needs to be applied to your $CATALINA_OPTS
environment variable in case of an external container.
Faster Startup
This guide provides several recommendations on how to make web applications and Apache Tomcat as a whole to start up faster.
Logging
The embedded Apache Tomcat container is presently unable to display any log messages below INFO even if your CAS log
configuration explicitly asks for DEBUG or TRACE level data.
See this bug report to learn more.
While workarounds and fixes may become available in the future, for the time being, you may execute the following
changes to get DEBUG level log data from the embedded Apache Tomcat. This
is specially useful if you are troubleshooting the behavior
of Tomcat’s internal components such as valves, etc.
- Design a
logging.propertiesfile as such:
1
2
3
4
handlers = java.util.logging.ConsoleHandler
.level = ALL
java.util.logging.ConsoleHandler.level = FINER
java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
- Design a
java.util.logging.config.filesetting as a system/environment variable or command-line argument whose value is set to thelogging.propertiespath. Use the setting when you launch and deploy CAS.
For instance:
1
java -jar /path/to/cas.war -Djava.util.logging.config.file=/path/to/logging.properties
Configuration
The following settings and properties are available from the CAS configuration catalog:
server.tomcat.accept-count=100
Maximum queue length for incoming connection requests when all possible request processing threads are in use. |
server.tomcat.accesslog.buffered=true
Whether to buffer output such that it is flushed only periodically. |
server.tomcat.accesslog.check-exists=false
Whether to check for log file existence so it can be recreated it if an external process has renamed it. |
server.tomcat.accesslog.condition-if=
Whether logging of the request will only be enabled if "ServletRequest.getAttribute(conditionIf)" does not yield null. |
server.tomcat.accesslog.condition-unless=
Whether logging of the request will only be enabled if "ServletRequest.getAttribute(conditionUnless)" yield null. |
server.tomcat.accesslog.directory=logs
Directory in which log files are created. Can be absolute or relative to the Tomcat base dir. |
server.tomcat.accesslog.enabled=false
Enable access log. |
server.tomcat.accesslog.encoding=
Character set used by the log file. Default to the system default character set. |
server.tomcat.accesslog.file-date-format=.yyyy-MM-dd
Date format to place in the log file name. |
server.tomcat.accesslog.ipv6-canonical=false
Whether to use IPv6 canonical representation format as defined by RFC 5952. |
server.tomcat.accesslog.locale=
Locale used to format timestamps in log entries and in log file name suffix. Default to the default locale of the Java process. |
server.tomcat.accesslog.max-days=-1
Number of days to retain the access log files before they are removed. |
server.tomcat.accesslog.pattern=common
Format pattern for access logs. |
server.tomcat.accesslog.prefix=access_log
Log file name prefix. |
server.tomcat.accesslog.rename-on-rotate=false
Whether to defer inclusion of the date stamp in the file name until rotate time. |
server.tomcat.accesslog.request-attributes-enabled=false
Set request attributes for the IP address, Hostname, protocol, and port used for the request. |
server.tomcat.accesslog.rotate=true
Whether to enable access log rotation. |
server.tomcat.accesslog.suffix=.log
Log file name suffix. |
server.tomcat.additional-tld-skip-patterns=
Comma-separated list of additional patterns that match jars to ignore for TLD scanning. The special '?' and '*' characters can be used in the pattern to match one and only one character and zero or more characters respectively. |
server.tomcat.background-processor-delay=10s
Delay between the invocation of backgroundProcess methods. If a duration suffix is not specified, seconds will be used. |
server.tomcat.basedir=
Tomcat base directory. If not specified, a temporary directory is used. |
server.tomcat.connection-timeout=
Amount of time the connector will wait, after accepting a connection, for the request URI line to be presented. |
server.tomcat.keep-alive-timeout=
Time to wait for another HTTP request before the connection is closed. When not set the connectionTimeout is used. When set to -1 there will be no timeout. |
server.tomcat.max-connections=8192
Maximum number of connections that the server accepts and processes at any given time. Once the limit has been reached, the operating system may still accept connections based on the "acceptCount" property. |
server.tomcat.max-http-form-post-size=2MB
Maximum size of the form content in any HTTP post request. |
server.tomcat.max-http-post-size=
Deprecation status is |
server.tomcat.max-keep-alive-requests=100
Maximum number of HTTP requests that can be pipelined before the connection is closed. When set to 0 or 1, keep-alive and pipelining are disabled. When set to -1, an unlimited number of pipelined or keep-alive requests are allowed. |
server.tomcat.max-swallow-size=2MB
Maximum amount of request body to swallow. |
server.tomcat.mbeanregistry.enabled=false
Whether Tomcat's MBean Registry should be enabled. |
server.tomcat.processor-cache=200
Maximum number of idle processors that will be retained in the cache and reused with a subsequent request. When set to -1 the cache will be unlimited with a theoretical maximum size equal to the maximum number of connections. |
server.tomcat.redirect-context-root=true
Whether requests to the context root should be redirected by appending a / to the path. When using SSL terminated at a proxy, this property should be set to false. |
server.tomcat.reject-illegal-header=true
Whether to reject requests with illegal header names or values. |
server.tomcat.relaxed-path-chars=
Comma-separated list of additional unencoded characters that should be allowed in URI paths. Only "< > [ \ ] ^ ` { | </code>" are allowed. |
server.tomcat.relaxed-query-chars=
Comma-separated list of additional unencoded characters that should be allowed in URI query strings. Only "< > [ \ ] ^ ` { | </code>" are allowed. |
server.tomcat.remoteip.host-header=X-Forwarded-Host
Name of the HTTP header from which the remote host is extracted. |
server.tomcat.remoteip.internal-proxies=10\.\d{1,3}\.\d{1,3}\.\d{1,3}|192\.168\.\d{1,3}\.\d{1,3}|169\.254\.\d{1,3}\.\d{1,3}|127\.\d{1,3}\.\d{1,3}\.\d{1,3}|172\.1[6-9]{1}\.\d{1,3}\.\d{1,3}|172\.2[0-9]{1}\.\d{1,3}\.\d{1,3}|172\.3[0-1]{1}\.\d{1,3}\.\d{1,3}|0:0:0:0:0:0:0:1|::1
Regular expression that matches proxies that are to be trusted. |
server.tomcat.remoteip.port-header=X-Forwarded-Port
Name of the HTTP header used to override the original port value. |
server.tomcat.remoteip.protocol-header=
Header that holds the incoming protocol, usually named "X-Forwarded-Proto". |
server.tomcat.remoteip.protocol-header-https-value=https
Value of the protocol header indicating whether the incoming request uses SSL. |
server.tomcat.remoteip.remote-ip-header=
Name of the HTTP header from which the remote IP is extracted. For instance, 'X-FORWARDED-FOR'. |
server.tomcat.remoteip.trusted-proxies=
Regular expression defining proxies that are trusted when they appear in the "remote-ip-header" header. |
server.tomcat.resource.allow-caching=true
Whether static resource caching is permitted for this web application. |
server.tomcat.resource.cache-ttl=
Time-to-live of the static resource cache. |
server.tomcat.threads.max=200
Maximum amount of worker threads. |
server.tomcat.threads.min-spare=10
Minimum amount of worker threads. |
server.tomcat.uri-encoding=UTF-8
Character encoding to use to decode the URI. |
server.tomcat.use-relative-redirects=false
Whether HTTP 1.1 and later location headers generated by a call to sendRedirect will use relative or absolute redirects. |
If you need to design your own password encoding scheme where the type is specified as a fully qualified Java class name, the structure of the class would be similar to the following:
1
2
3
4
5
6
7
8
9
10
11
package org.example.cas;
import org.springframework.security.crypto.codec.*;
import org.springframework.security.crypto.password.*;
public class MyEncoder extends AbstractPasswordEncoder {
@Override
protected byte[] encode(CharSequence rawPassword, byte[] salt) {
return ...
}
}
If you need to design your own password encoding scheme where the type is specified as a path to a Groovy script, the structure of the script would be similar to the following:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import java.util.*
byte[] run(final Object... args) {
def rawPassword = args[0]
def generatedSalt = args[1]
def logger = args[2]
def casApplicationContext = args[3]
logger.debug("Encoding password...")
return ...
}
Boolean matches(final Object... args) {
def rawPassword = args[0]
def encodedPassword = args[1]
def logger = args[2]
def casApplicationContext = args[3]
logger.debug("Does match or not ?");
return ...
Password Policy Strategies
If the password policy strategy is to be handed off to a Groovy script, the outline of the script may be as follows:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import java.util.*
import org.ldaptive.auth.*
import org.apereo.cas.*
import org.apereo.cas.authentication.*
import org.apereo.cas.authentication.support.*
List<MessageDescriptor> run(final Object... args) {
def response = args[0]
def configuration = args[1];
def logger = args[2]
def applicationContext = args[3]
logger.info("Handling password policy [{}] via ${configuration.getAccountStateHandler()}", response)
def accountStateHandler = configuration.getAccountStateHandler()
return accountStateHandler.handle(response, configuration)
}
The parameters passed are as follows:
| Parameter | Description |
|---|---|
response |
The LDAP authentication response of type org.ldaptive.auth.AuthenticationResponse |
configuration |
The LDAP password policy configuration carrying the account state handler defined. |
logger |
The object responsible for issuing log messages such as logger.info(...). |
Authentication handlers that generally deal with username-password credentials can be configured to transform the user id prior to executing the authentication sequence. Each authentication strategy in CAS provides settings to properly transform the principal. Refer to the relevant settings for the authentication strategy at hand to learn more.
Authentication handlers as part of principal transformation may also be provided a path to a Groovy script to transform the provided username. The outline of the script may take on the following form:
1
2
3
4
5
String run(final Object... args) {
def providedUsername = args[0]
def logger = args[1]
return providedUsername.concat("SomethingElse")
}
Configuration Metadata
The collection of configuration properties listed in this section are automatically generated from the CAS source and components that contain the actual field definitions, types, descriptions, modules, etc. This metadata may not always be 100% accurate, or could be lacking details and sufficient explanations.
Be Selective
This section is meant as a guide only. Do NOT copy/paste the entire collection of settings into your CAS configuration; rather pick only the properties that you need. Do NOT enable settings unless you are certain of their purpose and do NOT copy settings into your configuration only to keep them as reference. All these ideas lead to upgrade headaches, maintenance nightmares and premature aging.
YAGNI
Note that for nearly ALL use cases, declaring and configuring properties listed here is sufficient. You should NOT have to explicitly massage a CAS XML/Java/etc configuration file to design an authentication handler, create attribute release policies, etc. CAS at runtime will auto-configure all required changes for you. If you are unsure about the meaning of a given CAS setting, do NOT turn it on without hesitation. Review the codebase or better yet, ask questions to clarify the intended behavior.
Naming Convention
Property names can be specified in very relaxed terms. For instance cas.someProperty, cas.some-property, cas.some_property are all valid names. While all
forms are accepted by CAS, there are certain components (in CAS and other frameworks used) whose activation at runtime is conditional on a property value, where
this property is required to have been specified in CAS configuration using kebab case. This is both true for properties that are owned by CAS as well as those
that might be presented to the system via an external library or framework such as Spring Boot, etc.
When possible, properties should be stored in lower-case kebab format, such as cas.property-name=value.
The only possible exception to this rule is when naming actuator endpoints; The name of the
actuator endpoints (i.e. ssoSessions) MUST remain in camelCase mode.
Settings and properties that are controlled by the CAS platform directly always begin with the prefix cas. All other settings are controlled and provided
to CAS via other underlying frameworks and may have their own schemas and syntax. BE CAREFUL with
the distinction. Unrecognized properties are rejected by CAS and/or frameworks upon which CAS depends. This means if you somehow misspell a property definition
or fail to adhere to the dot-notation syntax and such, your setting is entirely refused by CAS and likely the feature it controls will never be activated in the
way you intend.
Validation
Configuration properties are automatically validated on CAS startup to report issues with configuration binding, specially if defined CAS settings cannot be
recognized or validated by the configuration schema. The validation process is on by default and can be skipped on startup using a special system
property SKIP_CONFIG_VALIDATION that should be set to true. Additional validation processes are also handled
via Configuration Metadata and property migrations applied automatically on
startup by Spring Boot and family.
Indexed Settings
CAS settings able to accept multiple values are typically documented with an index, such as cas.some.setting[0]=value. The index [0] is meant to be
incremented by the adopter to allow for distinct multiple configuration blocks.
HTTP && HTTP Proxying
The following settings and properties are available from the CAS configuration catalog:
cas.server.tomcat.http-proxy.enabled=false
Enable the container running in proxy mode. |
cas.server.tomcat.http[0].enabled=
Enable a separate port for the embedded container for HTTP access. |
cas.server.tomcat.http=
Embedded container HTTP port settings as an additional option. |
cas.server.tomcat.http-proxy.attributes=
Custom attributes to set on the proxy connector. |
cas.server.tomcat.http-proxy.protocol=AJP/1.3
Proxy protocol to use. |
cas.server.tomcat.http-proxy.proxy-port=0
Proxy port for the proxy. |
cas.server.tomcat.http-proxy.redirect-port=0
Redirect port for the proxy. |
cas.server.tomcat.http-proxy.scheme=https
Scheme used for the proxy. |
cas.server.tomcat.http-proxy.secret=
Set the secret that must be included with every request. |
cas.server.tomcat.http-proxy.secure=true
Whether proxy should run in secure mode. |
cas.server.tomcat.http[0].attributes=
Additional attributes to be set on the connector. |
cas.server.tomcat.http[0].port=8080
The HTTP port to use. |
cas.server.tomcat.http[0].protocol=org.apache.coyote.http11.Http11NioProtocol
HTTP protocol to use. |
cas.server.tomcat.http[0].redirect-port=
If this Connector is supporting non-SSL requests, this will automatically redirect the request to the port number specified here. Matching security constraints that require SSL transport will be auto-defined. |
cas.server.tomcat.http[0].scheme=http
Scheme used for the connector. |
cas.server.tomcat.http[0].secure=
Whether connector should run in secure mode. |
If you need to design your own password encoding scheme where the type is specified as a fully qualified Java class name, the structure of the class would be similar to the following:
1
2
3
4
5
6
7
8
9
10
11
package org.example.cas;
import org.springframework.security.crypto.codec.*;
import org.springframework.security.crypto.password.*;
public class MyEncoder extends AbstractPasswordEncoder {
@Override
protected byte[] encode(CharSequence rawPassword, byte[] salt) {
return ...
}
}
If you need to design your own password encoding scheme where the type is specified as a path to a Groovy script, the structure of the script would be similar to the following:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import java.util.*
byte[] run(final Object... args) {
def rawPassword = args[0]
def generatedSalt = args[1]
def logger = args[2]
def casApplicationContext = args[3]
logger.debug("Encoding password...")
return ...
}
Boolean matches(final Object... args) {
def rawPassword = args[0]
def encodedPassword = args[1]
def logger = args[2]
def casApplicationContext = args[3]
logger.debug("Does match or not ?");
return ...
Password Policy Strategies
If the password policy strategy is to be handed off to a Groovy script, the outline of the script may be as follows:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import java.util.*
import org.ldaptive.auth.*
import org.apereo.cas.*
import org.apereo.cas.authentication.*
import org.apereo.cas.authentication.support.*
List<MessageDescriptor> run(final Object... args) {
def response = args[0]
def configuration = args[1];
def logger = args[2]
def applicationContext = args[3]
logger.info("Handling password policy [{}] via ${configuration.getAccountStateHandler()}", response)
def accountStateHandler = configuration.getAccountStateHandler()
return accountStateHandler.handle(response, configuration)
}
The parameters passed are as follows:
| Parameter | Description |
|---|---|
response |
The LDAP authentication response of type org.ldaptive.auth.AuthenticationResponse |
configuration |
The LDAP password policy configuration carrying the account state handler defined. |
logger |
The object responsible for issuing log messages such as logger.info(...). |
Authentication handlers that generally deal with username-password credentials can be configured to transform the user id prior to executing the authentication sequence. Each authentication strategy in CAS provides settings to properly transform the principal. Refer to the relevant settings for the authentication strategy at hand to learn more.
Authentication handlers as part of principal transformation may also be provided a path to a Groovy script to transform the provided username. The outline of the script may take on the following form:
1
2
3
4
5
String run(final Object... args) {
def providedUsername = args[0]
def logger = args[1]
return providedUsername.concat("SomethingElse")
}
Configuration Metadata
The collection of configuration properties listed in this section are automatically generated from the CAS source and components that contain the actual field definitions, types, descriptions, modules, etc. This metadata may not always be 100% accurate, or could be lacking details and sufficient explanations.
Be Selective
This section is meant as a guide only. Do NOT copy/paste the entire collection of settings into your CAS configuration; rather pick only the properties that you need. Do NOT enable settings unless you are certain of their purpose and do NOT copy settings into your configuration only to keep them as reference. All these ideas lead to upgrade headaches, maintenance nightmares and premature aging.
YAGNI
Note that for nearly ALL use cases, declaring and configuring properties listed here is sufficient. You should NOT have to explicitly massage a CAS XML/Java/etc configuration file to design an authentication handler, create attribute release policies, etc. CAS at runtime will auto-configure all required changes for you. If you are unsure about the meaning of a given CAS setting, do NOT turn it on without hesitation. Review the codebase or better yet, ask questions to clarify the intended behavior.
Naming Convention
Property names can be specified in very relaxed terms. For instance cas.someProperty, cas.some-property, cas.some_property are all valid names. While all
forms are accepted by CAS, there are certain components (in CAS and other frameworks used) whose activation at runtime is conditional on a property value, where
this property is required to have been specified in CAS configuration using kebab case. This is both true for properties that are owned by CAS as well as those
that might be presented to the system via an external library or framework such as Spring Boot, etc.
When possible, properties should be stored in lower-case kebab format, such as cas.property-name=value.
The only possible exception to this rule is when naming actuator endpoints; The name of the
actuator endpoints (i.e. ssoSessions) MUST remain in camelCase mode.
Settings and properties that are controlled by the CAS platform directly always begin with the prefix cas. All other settings are controlled and provided
to CAS via other underlying frameworks and may have their own schemas and syntax. BE CAREFUL with
the distinction. Unrecognized properties are rejected by CAS and/or frameworks upon which CAS depends. This means if you somehow misspell a property definition
or fail to adhere to the dot-notation syntax and such, your setting is entirely refused by CAS and likely the feature it controls will never be activated in the
way you intend.
Validation
Configuration properties are automatically validated on CAS startup to report issues with configuration binding, specially if defined CAS settings cannot be
recognized or validated by the configuration schema. The validation process is on by default and can be skipped on startup using a special system
property SKIP_CONFIG_VALIDATION that should be set to true. Additional validation processes are also handled
via Configuration Metadata and property migrations applied automatically on
startup by Spring Boot and family.
Indexed Settings
CAS settings able to accept multiple values are typically documented with an index, such as cas.some.setting[0]=value. The index [0] is meant to be
incremented by the adopter to allow for distinct multiple configuration blocks.
AJP
The following settings and properties are available from the CAS configuration catalog:
cas.server.tomcat.ajp.enabled=false
Enable AJP support in CAS for the embedded Apache Tomcat container. |
cas.server.tomcat.ajp.allow-trace=false
A boolean value which can be used to enable or disable the TRACE HTTP method. If not specified, this attribute is set to false. |
cas.server.tomcat.ajp.async-timeout=PT5S
The default timeout for asynchronous requests in milliseconds. If not specified, this attribute is set to 10000 (10 seconds). This settings supports the
|
cas.server.tomcat.ajp.attributes=
Additional attributes to be set on the AJP connector in form of key-value pairs. Examples include:
|
cas.server.tomcat.ajp.enable-lookups=false
Set to true if you want calls to |
cas.server.tomcat.ajp.max-post-size=20971520
The maximum size in bytes of the POST which will be handled by the container FORM URL parameter parsing. The feature can be disabled by setting this attribute to a value less than or equal to 0. If not specified, this attribute is set to 2097152 (2 megabytes). |
cas.server.tomcat.ajp.port=8009
The TCP port number on which this Connector will create a server socket and await incoming connections. Your operating system will allow only one server application to listen to a particular port number on a particular IP address. If the special value of 0 (zero) is used, then Tomcat will select a free port at random to use for this connector. This is typically only useful in embedded and testing applications. |
cas.server.tomcat.ajp.protocol=AJP/1.3
Sets the protocol to handle incoming traffic. |
cas.server.tomcat.ajp.proxy-port=-1
If this Connector is being used in a proxy configuration, configure this attribute to specify the server port to be returned for calls to request.getServerPort(). |
cas.server.tomcat.ajp.redirect-port=-1
If this Connector is supporting non-SSL requests, and a request is received for which a matching |
cas.server.tomcat.ajp.scheme=http
Set this attribute to the name of the protocol you wish to have returned by calls to |
cas.server.tomcat.ajp.secret=
Set the secret that must be included with every request. |
cas.server.tomcat.ajp.secure=false
Set this attribute to true if you wish to have calls to request.isSecure() to return true for requests received by this Connector (you would want this on an SSL Connector). The default value is false. |
If you need to design your own password encoding scheme where the type is specified as a fully qualified Java class name, the structure of the class would be similar to the following:
1
2
3
4
5
6
7
8
9
10
11
package org.example.cas;
import org.springframework.security.crypto.codec.*;
import org.springframework.security.crypto.password.*;
public class MyEncoder extends AbstractPasswordEncoder {
@Override
protected byte[] encode(CharSequence rawPassword, byte[] salt) {
return ...
}
}
If you need to design your own password encoding scheme where the type is specified as a path to a Groovy script, the structure of the script would be similar to the following:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import java.util.*
byte[] run(final Object... args) {
def rawPassword = args[0]
def generatedSalt = args[1]
def logger = args[2]
def casApplicationContext = args[3]
logger.debug("Encoding password...")
return ...
}
Boolean matches(final Object... args) {
def rawPassword = args[0]
def encodedPassword = args[1]
def logger = args[2]
def casApplicationContext = args[3]
logger.debug("Does match or not ?");
return ...
Password Policy Strategies
If the password policy strategy is to be handed off to a Groovy script, the outline of the script may be as follows:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import java.util.*
import org.ldaptive.auth.*
import org.apereo.cas.*
import org.apereo.cas.authentication.*
import org.apereo.cas.authentication.support.*
List<MessageDescriptor> run(final Object... args) {
def response = args[0]
def configuration = args[1];
def logger = args[2]
def applicationContext = args[3]
logger.info("Handling password policy [{}] via ${configuration.getAccountStateHandler()}", response)
def accountStateHandler = configuration.getAccountStateHandler()
return accountStateHandler.handle(response, configuration)
}
The parameters passed are as follows:
| Parameter | Description |
|---|---|
response |
The LDAP authentication response of type org.ldaptive.auth.AuthenticationResponse |
configuration |
The LDAP password policy configuration carrying the account state handler defined. |
logger |
The object responsible for issuing log messages such as logger.info(...). |
Authentication handlers that generally deal with username-password credentials can be configured to transform the user id prior to executing the authentication sequence. Each authentication strategy in CAS provides settings to properly transform the principal. Refer to the relevant settings for the authentication strategy at hand to learn more.
Authentication handlers as part of principal transformation may also be provided a path to a Groovy script to transform the provided username. The outline of the script may take on the following form:
1
2
3
4
5
String run(final Object... args) {
def providedUsername = args[0]
def logger = args[1]
return providedUsername.concat("SomethingElse")
}
Configuration Metadata
The collection of configuration properties listed in this section are automatically generated from the CAS source and components that contain the actual field definitions, types, descriptions, modules, etc. This metadata may not always be 100% accurate, or could be lacking details and sufficient explanations.
Be Selective
This section is meant as a guide only. Do NOT copy/paste the entire collection of settings into your CAS configuration; rather pick only the properties that you need. Do NOT enable settings unless you are certain of their purpose and do NOT copy settings into your configuration only to keep them as reference. All these ideas lead to upgrade headaches, maintenance nightmares and premature aging.
YAGNI
Note that for nearly ALL use cases, declaring and configuring properties listed here is sufficient. You should NOT have to explicitly massage a CAS XML/Java/etc configuration file to design an authentication handler, create attribute release policies, etc. CAS at runtime will auto-configure all required changes for you. If you are unsure about the meaning of a given CAS setting, do NOT turn it on without hesitation. Review the codebase or better yet, ask questions to clarify the intended behavior.
Naming Convention
Property names can be specified in very relaxed terms. For instance cas.someProperty, cas.some-property, cas.some_property are all valid names. While all
forms are accepted by CAS, there are certain components (in CAS and other frameworks used) whose activation at runtime is conditional on a property value, where
this property is required to have been specified in CAS configuration using kebab case. This is both true for properties that are owned by CAS as well as those
that might be presented to the system via an external library or framework such as Spring Boot, etc.
When possible, properties should be stored in lower-case kebab format, such as cas.property-name=value.
The only possible exception to this rule is when naming actuator endpoints; The name of the
actuator endpoints (i.e. ssoSessions) MUST remain in camelCase mode.
Settings and properties that are controlled by the CAS platform directly always begin with the prefix cas. All other settings are controlled and provided
to CAS via other underlying frameworks and may have their own schemas and syntax. BE CAREFUL with
the distinction. Unrecognized properties are rejected by CAS and/or frameworks upon which CAS depends. This means if you somehow misspell a property definition
or fail to adhere to the dot-notation syntax and such, your setting is entirely refused by CAS and likely the feature it controls will never be activated in the
way you intend.
Validation
Configuration properties are automatically validated on CAS startup to report issues with configuration binding, specially if defined CAS settings cannot be
recognized or validated by the configuration schema. The validation process is on by default and can be skipped on startup using a special system
property SKIP_CONFIG_VALIDATION that should be set to true. Additional validation processes are also handled
via Configuration Metadata and property migrations applied automatically on
startup by Spring Boot and family.
Indexed Settings
CAS settings able to accept multiple values are typically documented with an index, such as cas.some.setting[0]=value. The index [0] is meant to be
incremented by the adopter to allow for distinct multiple configuration blocks.
SSL Valve
The Apache Tomcat SSLValve is a way to get a client certificate from an SSL proxy (e.g. HAProxy or BigIP F5)
running in front of Tomcat via an HTTP header. If you enable this, make sure your proxy is ensuring
that this header does not originate with the client (e.g. the browser).
The following settings and properties are available from the CAS configuration catalog:
cas.server.tomcat.ssl-valve.enabled=false
Enable the SSL valve for apache tomcat. |
cas.server.tomcat.ssl-valve.ssl-cipher-header=ssl_cipher
Allows setting a custom name for the ssl_cipher header. If not specified, the default of ssl_cipher is used. |
cas.server.tomcat.ssl-valve.ssl-cipher-user-key-size-header=ssl_cipher_usekeysize
Allows setting a custom name for the ssl_cipher_usekeysize header. If not specified, the default of ssl_cipher_usekeysize is used. |
cas.server.tomcat.ssl-valve.ssl-client-cert-header=ssl_client_cert
Allows setting a custom name for the ssl_client_cert header. If not specified, the default of ssl_client_cert is used. |
cas.server.tomcat.ssl-valve.ssl-session-id-header=ssl_session_id
Allows setting a custom name for the ssl_session_id header. If not specified, the default of ssl_session_id is used. |
If you need to design your own password encoding scheme where the type is specified as a fully qualified Java class name, the structure of the class would be similar to the following:
1
2
3
4
5
6
7
8
9
10
11
package org.example.cas;
import org.springframework.security.crypto.codec.*;
import org.springframework.security.crypto.password.*;
public class MyEncoder extends AbstractPasswordEncoder {
@Override
protected byte[] encode(CharSequence rawPassword, byte[] salt) {
return ...
}
}
If you need to design your own password encoding scheme where the type is specified as a path to a Groovy script, the structure of the script would be similar to the following:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import java.util.*
byte[] run(final Object... args) {
def rawPassword = args[0]
def generatedSalt = args[1]
def logger = args[2]
def casApplicationContext = args[3]
logger.debug("Encoding password...")
return ...
}
Boolean matches(final Object... args) {
def rawPassword = args[0]
def encodedPassword = args[1]
def logger = args[2]
def casApplicationContext = args[3]
logger.debug("Does match or not ?");
return ...
Password Policy Strategies
If the password policy strategy is to be handed off to a Groovy script, the outline of the script may be as follows:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import java.util.*
import org.ldaptive.auth.*
import org.apereo.cas.*
import org.apereo.cas.authentication.*
import org.apereo.cas.authentication.support.*
List<MessageDescriptor> run(final Object... args) {
def response = args[0]
def configuration = args[1];
def logger = args[2]
def applicationContext = args[3]
logger.info("Handling password policy [{}] via ${configuration.getAccountStateHandler()}", response)
def accountStateHandler = configuration.getAccountStateHandler()
return accountStateHandler.handle(response, configuration)
}
The parameters passed are as follows:
| Parameter | Description |
|---|---|
response |
The LDAP authentication response of type org.ldaptive.auth.AuthenticationResponse |
configuration |
The LDAP password policy configuration carrying the account state handler defined. |
logger |
The object responsible for issuing log messages such as logger.info(...). |
Authentication handlers that generally deal with username-password credentials can be configured to transform the user id prior to executing the authentication sequence. Each authentication strategy in CAS provides settings to properly transform the principal. Refer to the relevant settings for the authentication strategy at hand to learn more.
Authentication handlers as part of principal transformation may also be provided a path to a Groovy script to transform the provided username. The outline of the script may take on the following form:
1
2
3
4
5
String run(final Object... args) {
def providedUsername = args[0]
def logger = args[1]
return providedUsername.concat("SomethingElse")
}
Configuration Metadata
The collection of configuration properties listed in this section are automatically generated from the CAS source and components that contain the actual field definitions, types, descriptions, modules, etc. This metadata may not always be 100% accurate, or could be lacking details and sufficient explanations.
Be Selective
This section is meant as a guide only. Do NOT copy/paste the entire collection of settings into your CAS configuration; rather pick only the properties that you need. Do NOT enable settings unless you are certain of their purpose and do NOT copy settings into your configuration only to keep them as reference. All these ideas lead to upgrade headaches, maintenance nightmares and premature aging.
YAGNI
Note that for nearly ALL use cases, declaring and configuring properties listed here is sufficient. You should NOT have to explicitly massage a CAS XML/Java/etc configuration file to design an authentication handler, create attribute release policies, etc. CAS at runtime will auto-configure all required changes for you. If you are unsure about the meaning of a given CAS setting, do NOT turn it on without hesitation. Review the codebase or better yet, ask questions to clarify the intended behavior.
Naming Convention
Property names can be specified in very relaxed terms. For instance cas.someProperty, cas.some-property, cas.some_property are all valid names. While all
forms are accepted by CAS, there are certain components (in CAS and other frameworks used) whose activation at runtime is conditional on a property value, where
this property is required to have been specified in CAS configuration using kebab case. This is both true for properties that are owned by CAS as well as those
that might be presented to the system via an external library or framework such as Spring Boot, etc.
When possible, properties should be stored in lower-case kebab format, such as cas.property-name=value.
The only possible exception to this rule is when naming actuator endpoints; The name of the
actuator endpoints (i.e. ssoSessions) MUST remain in camelCase mode.
Settings and properties that are controlled by the CAS platform directly always begin with the prefix cas. All other settings are controlled and provided
to CAS via other underlying frameworks and may have their own schemas and syntax. BE CAREFUL with
the distinction. Unrecognized properties are rejected by CAS and/or frameworks upon which CAS depends. This means if you somehow misspell a property definition
or fail to adhere to the dot-notation syntax and such, your setting is entirely refused by CAS and likely the feature it controls will never be activated in the
way you intend.
Validation
Configuration properties are automatically validated on CAS startup to report issues with configuration binding, specially if defined CAS settings cannot be
recognized or validated by the configuration schema. The validation process is on by default and can be skipped on startup using a special system
property SKIP_CONFIG_VALIDATION that should be set to true. Additional validation processes are also handled
via Configuration Metadata and property migrations applied automatically on
startup by Spring Boot and family.
Indexed Settings
CAS settings able to accept multiple values are typically documented with an index, such as cas.some.setting[0]=value. The index [0] is meant to be
incremented by the adopter to allow for distinct multiple configuration blocks.
Example HAProxy Configuration (snippet): Configure SSL frontend with cert optional, redirect to cas, if cert provided, put it on header.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
frontend web-vip
bind 192.168.2.10:443 ssl crt /var/lib/haproxy/certs/www.example.com.pem ca-file /var/lib/haproxy/certs/ca.pem verify optional
mode http
acl www-cert ssl_fc_sni if { www.example.com }
acl empty-path path /
http-request redirect location /cas/ if empty-path www-cert
http-request del-header ssl_client_cert unless { ssl_fc_has_crt }
http-request set-header ssl_client_cert -----BEGIN\ CERTIFICATE-----\ %[ssl_c_der,base64]\ -----END\ CERTIFICATE-----\ if { ssl_fc_has_crt }
acl cas-path path_beg -i /cas
reqadd X-Forwarded-Proto:\ https
use_backend cas-pool if cas-path
backend cas-pool
option httpclose
option forwardfor
cookie SERVERID-cas insert indirect nocache
server cas-1 192.168.2.10:8080 check cookie cas-1
Extended Access Log Valve
The following settings and properties are available from the CAS configuration catalog:
cas.server.tomcat.ext-access-log.enabled=false
Flag to indicate whether extended log facility is enabled. |
cas.server.tomcat.ext-access-log.directory=
Directory name for extended log. |
cas.server.tomcat.ext-access-log.pattern=c-ip s-ip cs-uri sc-status time x-threadname x-H(secure) x-H(remoteUser)
String representing extended log pattern. |
cas.server.tomcat.ext-access-log.prefix=localhost_access_extended
File name prefix for extended log. |
cas.server.tomcat.ext-access-log.suffix=.log
File name suffix for extended log. |
If you need to design your own password encoding scheme where the type is specified as a fully qualified Java class name, the structure of the class would be similar to the following:
1
2
3
4
5
6
7
8
9
10
11
package org.example.cas;
import org.springframework.security.crypto.codec.*;
import org.springframework.security.crypto.password.*;
public class MyEncoder extends AbstractPasswordEncoder {
@Override
protected byte[] encode(CharSequence rawPassword, byte[] salt) {
return ...
}
}
If you need to design your own password encoding scheme where the type is specified as a path to a Groovy script, the structure of the script would be similar to the following:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import java.util.*
byte[] run(final Object... args) {
def rawPassword = args[0]
def generatedSalt = args[1]
def logger = args[2]
def casApplicationContext = args[3]
logger.debug("Encoding password...")
return ...
}
Boolean matches(final Object... args) {
def rawPassword = args[0]
def encodedPassword = args[1]
def logger = args[2]
def casApplicationContext = args[3]
logger.debug("Does match or not ?");
return ...
Password Policy Strategies
If the password policy strategy is to be handed off to a Groovy script, the outline of the script may be as follows:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import java.util.*
import org.ldaptive.auth.*
import org.apereo.cas.*
import org.apereo.cas.authentication.*
import org.apereo.cas.authentication.support.*
List<MessageDescriptor> run(final Object... args) {
def response = args[0]
def configuration = args[1];
def logger = args[2]
def applicationContext = args[3]
logger.info("Handling password policy [{}] via ${configuration.getAccountStateHandler()}", response)
def accountStateHandler = configuration.getAccountStateHandler()
return accountStateHandler.handle(response, configuration)
}
The parameters passed are as follows:
| Parameter | Description |
|---|---|
response |
The LDAP authentication response of type org.ldaptive.auth.AuthenticationResponse |
configuration |
The LDAP password policy configuration carrying the account state handler defined. |
logger |
The object responsible for issuing log messages such as logger.info(...). |
Authentication handlers that generally deal with username-password credentials can be configured to transform the user id prior to executing the authentication sequence. Each authentication strategy in CAS provides settings to properly transform the principal. Refer to the relevant settings for the authentication strategy at hand to learn more.
Authentication handlers as part of principal transformation may also be provided a path to a Groovy script to transform the provided username. The outline of the script may take on the following form:
1
2
3
4
5
String run(final Object... args) {
def providedUsername = args[0]
def logger = args[1]
return providedUsername.concat("SomethingElse")
}
Configuration Metadata
The collection of configuration properties listed in this section are automatically generated from the CAS source and components that contain the actual field definitions, types, descriptions, modules, etc. This metadata may not always be 100% accurate, or could be lacking details and sufficient explanations.
Be Selective
This section is meant as a guide only. Do NOT copy/paste the entire collection of settings into your CAS configuration; rather pick only the properties that you need. Do NOT enable settings unless you are certain of their purpose and do NOT copy settings into your configuration only to keep them as reference. All these ideas lead to upgrade headaches, maintenance nightmares and premature aging.
YAGNI
Note that for nearly ALL use cases, declaring and configuring properties listed here is sufficient. You should NOT have to explicitly massage a CAS XML/Java/etc configuration file to design an authentication handler, create attribute release policies, etc. CAS at runtime will auto-configure all required changes for you. If you are unsure about the meaning of a given CAS setting, do NOT turn it on without hesitation. Review the codebase or better yet, ask questions to clarify the intended behavior.
Naming Convention
Property names can be specified in very relaxed terms. For instance cas.someProperty, cas.some-property, cas.some_property are all valid names. While all
forms are accepted by CAS, there are certain components (in CAS and other frameworks used) whose activation at runtime is conditional on a property value, where
this property is required to have been specified in CAS configuration using kebab case. This is both true for properties that are owned by CAS as well as those
that might be presented to the system via an external library or framework such as Spring Boot, etc.
When possible, properties should be stored in lower-case kebab format, such as cas.property-name=value.
The only possible exception to this rule is when naming actuator endpoints; The name of the
actuator endpoints (i.e. ssoSessions) MUST remain in camelCase mode.
Settings and properties that are controlled by the CAS platform directly always begin with the prefix cas. All other settings are controlled and provided
to CAS via other underlying frameworks and may have their own schemas and syntax. BE CAREFUL with
the distinction. Unrecognized properties are rejected by CAS and/or frameworks upon which CAS depends. This means if you somehow misspell a property definition
or fail to adhere to the dot-notation syntax and such, your setting is entirely refused by CAS and likely the feature it controls will never be activated in the
way you intend.
Validation
Configuration properties are automatically validated on CAS startup to report issues with configuration binding, specially if defined CAS settings cannot be
recognized or validated by the configuration schema. The validation process is on by default and can be skipped on startup using a special system
property SKIP_CONFIG_VALIDATION that should be set to true. Additional validation processes are also handled
via Configuration Metadata and property migrations applied automatically on
startup by Spring Boot and family.
Indexed Settings
CAS settings able to accept multiple values are typically documented with an index, such as cas.some.setting[0]=value. The index [0] is meant to be
incremented by the adopter to allow for distinct multiple configuration blocks.
Rewrite Valve
The following settings and properties are available from the CAS configuration catalog:
cas.server.tomcat.rewrite-valve.location=
Location of a rewrite valve specifically by Apache Tomcat to activate URL rewriting. |
If you need to design your own password encoding scheme where the type is specified as a fully qualified Java class name, the structure of the class would be similar to the following:
1
2
3
4
5
6
7
8
9
10
11
package org.example.cas;
import org.springframework.security.crypto.codec.*;
import org.springframework.security.crypto.password.*;
public class MyEncoder extends AbstractPasswordEncoder {
@Override
protected byte[] encode(CharSequence rawPassword, byte[] salt) {
return ...
}
}
If you need to design your own password encoding scheme where the type is specified as a path to a Groovy script, the structure of the script would be similar to the following:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import java.util.*
byte[] run(final Object... args) {
def rawPassword = args[0]
def generatedSalt = args[1]
def logger = args[2]
def casApplicationContext = args[3]
logger.debug("Encoding password...")
return ...
}
Boolean matches(final Object... args) {
def rawPassword = args[0]
def encodedPassword = args[1]
def logger = args[2]
def casApplicationContext = args[3]
logger.debug("Does match or not ?");
return ...
Password Policy Strategies
If the password policy strategy is to be handed off to a Groovy script, the outline of the script may be as follows:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import java.util.*
import org.ldaptive.auth.*
import org.apereo.cas.*
import org.apereo.cas.authentication.*
import org.apereo.cas.authentication.support.*
List<MessageDescriptor> run(final Object... args) {
def response = args[0]
def configuration = args[1];
def logger = args[2]
def applicationContext = args[3]
logger.info("Handling password policy [{}] via ${configuration.getAccountStateHandler()}", response)
def accountStateHandler = configuration.getAccountStateHandler()
return accountStateHandler.handle(response, configuration)
}
The parameters passed are as follows:
| Parameter | Description |
|---|---|
response |
The LDAP authentication response of type org.ldaptive.auth.AuthenticationResponse |
configuration |
The LDAP password policy configuration carrying the account state handler defined. |
logger |
The object responsible for issuing log messages such as logger.info(...). |
Authentication handlers that generally deal with username-password credentials can be configured to transform the user id prior to executing the authentication sequence. Each authentication strategy in CAS provides settings to properly transform the principal. Refer to the relevant settings for the authentication strategy at hand to learn more.
Authentication handlers as part of principal transformation may also be provided a path to a Groovy script to transform the provided username. The outline of the script may take on the following form:
1
2
3
4
5
String run(final Object... args) {
def providedUsername = args[0]
def logger = args[1]
return providedUsername.concat("SomethingElse")
}
Configuration Metadata
The collection of configuration properties listed in this section are automatically generated from the CAS source and components that contain the actual field definitions, types, descriptions, modules, etc. This metadata may not always be 100% accurate, or could be lacking details and sufficient explanations.
Be Selective
This section is meant as a guide only. Do NOT copy/paste the entire collection of settings into your CAS configuration; rather pick only the properties that you need. Do NOT enable settings unless you are certain of their purpose and do NOT copy settings into your configuration only to keep them as reference. All these ideas lead to upgrade headaches, maintenance nightmares and premature aging.
YAGNI
Note that for nearly ALL use cases, declaring and configuring properties listed here is sufficient. You should NOT have to explicitly massage a CAS XML/Java/etc configuration file to design an authentication handler, create attribute release policies, etc. CAS at runtime will auto-configure all required changes for you. If you are unsure about the meaning of a given CAS setting, do NOT turn it on without hesitation. Review the codebase or better yet, ask questions to clarify the intended behavior.
Naming Convention
Property names can be specified in very relaxed terms. For instance cas.someProperty, cas.some-property, cas.some_property are all valid names. While all
forms are accepted by CAS, there are certain components (in CAS and other frameworks used) whose activation at runtime is conditional on a property value, where
this property is required to have been specified in CAS configuration using kebab case. This is both true for properties that are owned by CAS as well as those
that might be presented to the system via an external library or framework such as Spring Boot, etc.
When possible, properties should be stored in lower-case kebab format, such as cas.property-name=value.
The only possible exception to this rule is when naming actuator endpoints; The name of the
actuator endpoints (i.e. ssoSessions) MUST remain in camelCase mode.
Settings and properties that are controlled by the CAS platform directly always begin with the prefix cas. All other settings are controlled and provided
to CAS via other underlying frameworks and may have their own schemas and syntax. BE CAREFUL with
the distinction. Unrecognized properties are rejected by CAS and/or frameworks upon which CAS depends. This means if you somehow misspell a property definition
or fail to adhere to the dot-notation syntax and such, your setting is entirely refused by CAS and likely the feature it controls will never be activated in the
way you intend.
Validation
Configuration properties are automatically validated on CAS startup to report issues with configuration binding, specially if defined CAS settings cannot be
recognized or validated by the configuration schema. The validation process is on by default and can be skipped on startup using a special system
property SKIP_CONFIG_VALIDATION that should be set to true. Additional validation processes are also handled
via Configuration Metadata and property migrations applied automatically on
startup by Spring Boot and family.
Indexed Settings
CAS settings able to accept multiple values are typically documented with an index, such as cas.some.setting[0]=value. The index [0] is meant to be
incremented by the adopter to allow for distinct multiple configuration blocks.
Basic Authentication
The following settings and properties are available from the CAS configuration catalog:
cas.server.tomcat.basic-authn.enabled=false
Enable Basic authentication for Tomcat. |
cas.server.tomcat.basic-authn.auth-roles=
Add an authorization role, which is a role name that will be permitted access to the resources protected by this security constraint. |
cas.server.tomcat.basic-authn.patterns=
Add a URL pattern to be part of this web resource collection. |
cas.server.tomcat.basic-authn.security-roles=
Security roles for the CAS application. |
If you need to design your own password encoding scheme where the type is specified as a fully qualified Java class name, the structure of the class would be similar to the following:
1
2
3
4
5
6
7
8
9
10
11
package org.example.cas;
import org.springframework.security.crypto.codec.*;
import org.springframework.security.crypto.password.*;
public class MyEncoder extends AbstractPasswordEncoder {
@Override
protected byte[] encode(CharSequence rawPassword, byte[] salt) {
return ...
}
}
If you need to design your own password encoding scheme where the type is specified as a path to a Groovy script, the structure of the script would be similar to the following:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import java.util.*
byte[] run(final Object... args) {
def rawPassword = args[0]
def generatedSalt = args[1]
def logger = args[2]
def casApplicationContext = args[3]
logger.debug("Encoding password...")
return ...
}
Boolean matches(final Object... args) {
def rawPassword = args[0]
def encodedPassword = args[1]
def logger = args[2]
def casApplicationContext = args[3]
logger.debug("Does match or not ?");
return ...
Password Policy Strategies
If the password policy strategy is to be handed off to a Groovy script, the outline of the script may be as follows:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import java.util.*
import org.ldaptive.auth.*
import org.apereo.cas.*
import org.apereo.cas.authentication.*
import org.apereo.cas.authentication.support.*
List<MessageDescriptor> run(final Object... args) {
def response = args[0]
def configuration = args[1];
def logger = args[2]
def applicationContext = args[3]
logger.info("Handling password policy [{}] via ${configuration.getAccountStateHandler()}", response)
def accountStateHandler = configuration.getAccountStateHandler()
return accountStateHandler.handle(response, configuration)
}
The parameters passed are as follows:
| Parameter | Description |
|---|---|
response |
The LDAP authentication response of type org.ldaptive.auth.AuthenticationResponse |
configuration |
The LDAP password policy configuration carrying the account state handler defined. |
logger |
The object responsible for issuing log messages such as logger.info(...). |
Authentication handlers that generally deal with username-password credentials can be configured to transform the user id prior to executing the authentication sequence. Each authentication strategy in CAS provides settings to properly transform the principal. Refer to the relevant settings for the authentication strategy at hand to learn more.
Authentication handlers as part of principal transformation may also be provided a path to a Groovy script to transform the provided username. The outline of the script may take on the following form:
1
2
3
4
5
String run(final Object... args) {
def providedUsername = args[0]
def logger = args[1]
return providedUsername.concat("SomethingElse")
}
Configuration Metadata
The collection of configuration properties listed in this section are automatically generated from the CAS source and components that contain the actual field definitions, types, descriptions, modules, etc. This metadata may not always be 100% accurate, or could be lacking details and sufficient explanations.
Be Selective
This section is meant as a guide only. Do NOT copy/paste the entire collection of settings into your CAS configuration; rather pick only the properties that you need. Do NOT enable settings unless you are certain of their purpose and do NOT copy settings into your configuration only to keep them as reference. All these ideas lead to upgrade headaches, maintenance nightmares and premature aging.
YAGNI
Note that for nearly ALL use cases, declaring and configuring properties listed here is sufficient. You should NOT have to explicitly massage a CAS XML/Java/etc configuration file to design an authentication handler, create attribute release policies, etc. CAS at runtime will auto-configure all required changes for you. If you are unsure about the meaning of a given CAS setting, do NOT turn it on without hesitation. Review the codebase or better yet, ask questions to clarify the intended behavior.
Naming Convention
Property names can be specified in very relaxed terms. For instance cas.someProperty, cas.some-property, cas.some_property are all valid names. While all
forms are accepted by CAS, there are certain components (in CAS and other frameworks used) whose activation at runtime is conditional on a property value, where
this property is required to have been specified in CAS configuration using kebab case. This is both true for properties that are owned by CAS as well as those
that might be presented to the system via an external library or framework such as Spring Boot, etc.
When possible, properties should be stored in lower-case kebab format, such as cas.property-name=value.
The only possible exception to this rule is when naming actuator endpoints; The name of the
actuator endpoints (i.e. ssoSessions) MUST remain in camelCase mode.
Settings and properties that are controlled by the CAS platform directly always begin with the prefix cas. All other settings are controlled and provided
to CAS via other underlying frameworks and may have their own schemas and syntax. BE CAREFUL with
the distinction. Unrecognized properties are rejected by CAS and/or frameworks upon which CAS depends. This means if you somehow misspell a property definition
or fail to adhere to the dot-notation syntax and such, your setting is entirely refused by CAS and likely the feature it controls will never be activated in the
way you intend.
Validation
Configuration properties are automatically validated on CAS startup to report issues with configuration binding, specially if defined CAS settings cannot be
recognized or validated by the configuration schema. The validation process is on by default and can be skipped on startup using a special system
property SKIP_CONFIG_VALIDATION that should be set to true. Additional validation processes are also handled
via Configuration Metadata and property migrations applied automatically on
startup by Spring Boot and family.
Indexed Settings
CAS settings able to accept multiple values are typically documented with an index, such as cas.some.setting[0]=value. The index [0] is meant to be
incremented by the adopter to allow for distinct multiple configuration blocks.
Apache Portable Runtime (APR)
Apache Tomcat can use the Apache Portable Runtime to provide superior scalability, performance, and better integration with native server technologies.
The following settings and properties are available from the CAS configuration catalog:
If you need to design your own password encoding scheme where the type is specified as a fully qualified Java class name, the structure of the class would be similar to the following:
1
2
3
4
5
6
7
8
9
10
11
package org.example.cas;
import org.springframework.security.crypto.codec.*;
import org.springframework.security.crypto.password.*;
public class MyEncoder extends AbstractPasswordEncoder {
@Override
protected byte[] encode(CharSequence rawPassword, byte[] salt) {
return ...
}
}
If you need to design your own password encoding scheme where the type is specified as a path to a Groovy script, the structure of the script would be similar to the following:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import java.util.*
byte[] run(final Object... args) {
def rawPassword = args[0]
def generatedSalt = args[1]
def logger = args[2]
def casApplicationContext = args[3]
logger.debug("Encoding password...")
return ...
}
Boolean matches(final Object... args) {
def rawPassword = args[0]
def encodedPassword = args[1]
def logger = args[2]
def casApplicationContext = args[3]
logger.debug("Does match or not ?");
return ...
Password Policy Strategies
If the password policy strategy is to be handed off to a Groovy script, the outline of the script may be as follows:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import java.util.*
import org.ldaptive.auth.*
import org.apereo.cas.*
import org.apereo.cas.authentication.*
import org.apereo.cas.authentication.support.*
List<MessageDescriptor> run(final Object... args) {
def response = args[0]
def configuration = args[1];
def logger = args[2]
def applicationContext = args[3]
logger.info("Handling password policy [{}] via ${configuration.getAccountStateHandler()}", response)
def accountStateHandler = configuration.getAccountStateHandler()
return accountStateHandler.handle(response, configuration)
}
The parameters passed are as follows:
| Parameter | Description |
|---|---|
response |
The LDAP authentication response of type org.ldaptive.auth.AuthenticationResponse |
configuration |
The LDAP password policy configuration carrying the account state handler defined. |
logger |
The object responsible for issuing log messages such as logger.info(...). |
Authentication handlers that generally deal with username-password credentials can be configured to transform the user id prior to executing the authentication sequence. Each authentication strategy in CAS provides settings to properly transform the principal. Refer to the relevant settings for the authentication strategy at hand to learn more.
Authentication handlers as part of principal transformation may also be provided a path to a Groovy script to transform the provided username. The outline of the script may take on the following form:
1
2
3
4
5
String run(final Object... args) {
def providedUsername = args[0]
def logger = args[1]
return providedUsername.concat("SomethingElse")
}
Configuration Metadata
The collection of configuration properties listed in this section are automatically generated from the CAS source and components that contain the actual field definitions, types, descriptions, modules, etc. This metadata may not always be 100% accurate, or could be lacking details and sufficient explanations.
Be Selective
This section is meant as a guide only. Do NOT copy/paste the entire collection of settings into your CAS configuration; rather pick only the properties that you need. Do NOT enable settings unless you are certain of their purpose and do NOT copy settings into your configuration only to keep them as reference. All these ideas lead to upgrade headaches, maintenance nightmares and premature aging.
YAGNI
Note that for nearly ALL use cases, declaring and configuring properties listed here is sufficient. You should NOT have to explicitly massage a CAS XML/Java/etc configuration file to design an authentication handler, create attribute release policies, etc. CAS at runtime will auto-configure all required changes for you. If you are unsure about the meaning of a given CAS setting, do NOT turn it on without hesitation. Review the codebase or better yet, ask questions to clarify the intended behavior.
Naming Convention
Property names can be specified in very relaxed terms. For instance cas.someProperty, cas.some-property, cas.some_property are all valid names. While all
forms are accepted by CAS, there are certain components (in CAS and other frameworks used) whose activation at runtime is conditional on a property value, where
this property is required to have been specified in CAS configuration using kebab case. This is both true for properties that are owned by CAS as well as those
that might be presented to the system via an external library or framework such as Spring Boot, etc.
When possible, properties should be stored in lower-case kebab format, such as cas.property-name=value.
The only possible exception to this rule is when naming actuator endpoints; The name of the
actuator endpoints (i.e. ssoSessions) MUST remain in camelCase mode.
Settings and properties that are controlled by the CAS platform directly always begin with the prefix cas. All other settings are controlled and provided
to CAS via other underlying frameworks and may have their own schemas and syntax. BE CAREFUL with
the distinction. Unrecognized properties are rejected by CAS and/or frameworks upon which CAS depends. This means if you somehow misspell a property definition
or fail to adhere to the dot-notation syntax and such, your setting is entirely refused by CAS and likely the feature it controls will never be activated in the
way you intend.
Validation
Configuration properties are automatically validated on CAS startup to report issues with configuration binding, specially if defined CAS settings cannot be
recognized or validated by the configuration schema. The validation process is on by default and can be skipped on startup using a special system
property SKIP_CONFIG_VALIDATION that should be set to true. Additional validation processes are also handled
via Configuration Metadata and property migrations applied automatically on
startup by Spring Boot and family.
Indexed Settings
CAS settings able to accept multiple values are typically documented with an index, such as cas.some.setting[0]=value. The index [0] is meant to be
incremented by the adopter to allow for distinct multiple configuration blocks.
Enabling APR requires the following JVM system property that indicates
the location of the APR library binaries (i.e. usr/local/opt/tomcat-native/lib):
1
-Djava.library.path=/path/to/tomcat-native/lib
Connector IO
The following settings and properties are available from the CAS configuration catalog:
cas.server.tomcat.socket.app-read-buf-size=0
Each connection that is opened up in Tomcat get associated with a read ByteBuffer. This attribute controls the size of this buffer. By default this read buffer is sized at 8192 bytes. For lower concurrency, you can increase this to buffer more data. For an extreme amount of keep alive connections, decrease this number or increase your heap size. |
cas.server.tomcat.socket.app-write-buf-size=0
Each connection that is opened up in Tomcat get associated with a write ByteBuffer. This attribute controls the size of this buffer. By default this write buffer is sized at 8192 bytes. For low concurrency you can increase this to buffer more response data. For an extreme amount of keep alive connections, decrease this number or increase your heap size. The default value here is pretty low, you should up it if you are not dealing with tens of thousands concurrent connections. |
cas.server.tomcat.socket.buffer-pool=0
The NIO connector uses a class called NioChannel that holds elements linked to a socket. To reduce garbage collection, the NIO connector caches these channel objects. This value specifies the size of this cache. The default value is 500, and represents that the cache will hold 500 NioChannel objects. Other values are -1 for unlimited cache and 0 for no cache. |
cas.server.tomcat.socket.performance-bandwidth=-1
An int expressing the relative importance of high bandwidth. Performance preferences are described by three integers whose values indicate the relative importance of short connection time, low latency, and high bandwidth. The absolute values of the integers are irrelevant; in order to choose a protocol the values are compared, with larger values indicating stronger preferences. Negative values disable the setting. If the application prefers short connection time over both low latency and high bandwidth, for example, then it could invoke this method with the values (1, 0, 0). If the application prefers high bandwidth above low latency, and low latency above short connection time, then it could invoke this method with the values (0, 1, 2). |
cas.server.tomcat.socket.performance-connection-time=-1
An int expressing the relative importance of a short connection time. Performance preferences are described by three integers whose values indicate the relative importance of short connection time, low latency, and high bandwidth. The absolute values of the integers are irrelevant; in order to choose a protocol the values are compared, with larger values indicating stronger preferences. Negative values disable the setting. If the application prefers short connection time over both low latency and high bandwidth, for example, then it could invoke this method with the values (1, 0, 0). If the application prefers high bandwidth above low latency, and low latency above short connection time, then it could invoke this method with the values (0, 1, 2). |
cas.server.tomcat.socket.performance-latency=-1
An int expressing the relative importance of low latency. Performance preferences are described by three integers whose values indicate the relative importance of short connection time, low latency, and high bandwidth. The absolute values of the integers are irrelevant; in order to choose a protocol the values are compared, with larger values indicating stronger preferences. Negative values disable the setting. If the application prefers short connection time over both low latency and high bandwidth, for example, then it could invoke this method with the values (1, 0, 0). If the application prefers high bandwidth above low latency, and low latency above short connection time, then it could invoke this method with the values (0, 1, 2). |
If you need to design your own password encoding scheme where the type is specified as a fully qualified Java class name, the structure of the class would be similar to the following:
1
2
3
4
5
6
7
8
9
10
11
package org.example.cas;
import org.springframework.security.crypto.codec.*;
import org.springframework.security.crypto.password.*;
public class MyEncoder extends AbstractPasswordEncoder {
@Override
protected byte[] encode(CharSequence rawPassword, byte[] salt) {
return ...
}
}
If you need to design your own password encoding scheme where the type is specified as a path to a Groovy script, the structure of the script would be similar to the following:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import java.util.*
byte[] run(final Object... args) {
def rawPassword = args[0]
def generatedSalt = args[1]
def logger = args[2]
def casApplicationContext = args[3]
logger.debug("Encoding password...")
return ...
}
Boolean matches(final Object... args) {
def rawPassword = args[0]
def encodedPassword = args[1]
def logger = args[2]
def casApplicationContext = args[3]
logger.debug("Does match or not ?");
return ...
Password Policy Strategies
If the password policy strategy is to be handed off to a Groovy script, the outline of the script may be as follows:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import java.util.*
import org.ldaptive.auth.*
import org.apereo.cas.*
import org.apereo.cas.authentication.*
import org.apereo.cas.authentication.support.*
List<MessageDescriptor> run(final Object... args) {
def response = args[0]
def configuration = args[1];
def logger = args[2]
def applicationContext = args[3]
logger.info("Handling password policy [{}] via ${configuration.getAccountStateHandler()}", response)
def accountStateHandler = configuration.getAccountStateHandler()
return accountStateHandler.handle(response, configuration)
}
The parameters passed are as follows:
| Parameter | Description |
|---|---|
response |
The LDAP authentication response of type org.ldaptive.auth.AuthenticationResponse |
configuration |
The LDAP password policy configuration carrying the account state handler defined. |
logger |
The object responsible for issuing log messages such as logger.info(...). |
Authentication handlers that generally deal with username-password credentials can be configured to transform the user id prior to executing the authentication sequence. Each authentication strategy in CAS provides settings to properly transform the principal. Refer to the relevant settings for the authentication strategy at hand to learn more.
Authentication handlers as part of principal transformation may also be provided a path to a Groovy script to transform the provided username. The outline of the script may take on the following form:
1
2
3
4
5
String run(final Object... args) {
def providedUsername = args[0]
def logger = args[1]
return providedUsername.concat("SomethingElse")
}
Configuration Metadata
The collection of configuration properties listed in this section are automatically generated from the CAS source and components that contain the actual field definitions, types, descriptions, modules, etc. This metadata may not always be 100% accurate, or could be lacking details and sufficient explanations.
Be Selective
This section is meant as a guide only. Do NOT copy/paste the entire collection of settings into your CAS configuration; rather pick only the properties that you need. Do NOT enable settings unless you are certain of their purpose and do NOT copy settings into your configuration only to keep them as reference. All these ideas lead to upgrade headaches, maintenance nightmares and premature aging.
YAGNI
Note that for nearly ALL use cases, declaring and configuring properties listed here is sufficient. You should NOT have to explicitly massage a CAS XML/Java/etc configuration file to design an authentication handler, create attribute release policies, etc. CAS at runtime will auto-configure all required changes for you. If you are unsure about the meaning of a given CAS setting, do NOT turn it on without hesitation. Review the codebase or better yet, ask questions to clarify the intended behavior.
Naming Convention
Property names can be specified in very relaxed terms. For instance cas.someProperty, cas.some-property, cas.some_property are all valid names. While all
forms are accepted by CAS, there are certain components (in CAS and other frameworks used) whose activation at runtime is conditional on a property value, where
this property is required to have been specified in CAS configuration using kebab case. This is both true for properties that are owned by CAS as well as those
that might be presented to the system via an external library or framework such as Spring Boot, etc.
When possible, properties should be stored in lower-case kebab format, such as cas.property-name=value.
The only possible exception to this rule is when naming actuator endpoints; The name of the
actuator endpoints (i.e. ssoSessions) MUST remain in camelCase mode.
Settings and properties that are controlled by the CAS platform directly always begin with the prefix cas. All other settings are controlled and provided
to CAS via other underlying frameworks and may have their own schemas and syntax. BE CAREFUL with
the distinction. Unrecognized properties are rejected by CAS and/or frameworks upon which CAS depends. This means if you somehow misspell a property definition
or fail to adhere to the dot-notation syntax and such, your setting is entirely refused by CAS and likely the feature it controls will never be activated in the
way you intend.
Validation
Configuration properties are automatically validated on CAS startup to report issues with configuration binding, specially if defined CAS settings cannot be
recognized or validated by the configuration schema. The validation process is on by default and can be skipped on startup using a special system
property SKIP_CONFIG_VALIDATION that should be set to true. Additional validation processes are also handled
via Configuration Metadata and property migrations applied automatically on
startup by Spring Boot and family.
Indexed Settings
CAS settings able to accept multiple values are typically documented with an index, such as cas.some.setting[0]=value. The index [0] is meant to be
incremented by the adopter to allow for distinct multiple configuration blocks.
Session Clustering & Replication
Enable in-memory session replication to replicate web application session deltas.
| Clustering Type | Description |
|---|---|
DEFAULT |
Discovers cluster members via multicast discovery and optionally via staticly defined cluster members using the clusterMembers. SimpleTcpCluster with McastService |
CLOUD |
For use in Kubernetes where members are discovered via accessing the Kubernetes API or doing a DNS lookup of the members of a Kubernetes service. Documentation is currently light, see code for details. |
| Membership Providers | Description |
|---|---|
kubernetes |
Uses Kubernetes API to find other pods in a deployment. API is discovered and accessed via information in environment variables set in the container. The KUBERNETES_NAMESPACE environment variable is used to query the pods in the namespace and it will treat other pods in that namespace as potential cluster members but they can be filtered using the KUBERNETES_LABELS environment variable which are used as a label selector. |
dns |
Uses DNS lookups to find addresses of the cluster members behind a DNS name specified by DNS_MEMBERSHIP_SERVICE_NAME environment variable. Works in Kubernetes but doesn’t rely on Kubernetes. |
MembershipProvider class |
Use a membership provider implementation of your choice. |
Most settings apply to the DEFAULT clustering type, which requires members to be defined via clusterMembers if multicast discovery doesn’t work. The cloudMembershipProvider setting applies to the CLOUD type.
The following settings and properties are available from the CAS configuration catalog:
cas.server.tomcat.clustering.enabled=false
Enable tomcat session clustering. |
cas.server.tomcat.clustering.channel-send-options=8
This option is used to set the flag that all messages sent through the SimpleTcpCluster uses. The flag decides how the messages are sent, and is a simple logical OR.
|
cas.server.tomcat.clustering.cloud-membership-provider=dns
Cloud membership provider, values are case sensitive and only used with clusteringType
|
cas.server.tomcat.clustering.cluster-members=
Statically register members in the cluster. The syntax is: |
cas.server.tomcat.clustering.clustering-type=DEFAULT
Accepted values are: |
cas.server.tomcat.clustering.expire-sessions-on-shutdown=false
When a web application is being shutdown, Tomcat issues an expire call to each session to notify all the listeners. If you wish for all sessions to expire on all nodes when a shutdown occurs on one node, set this value to true. Default value is false. |
cas.server.tomcat.clustering.manager-type=DELTA
Accepted values are: |
cas.server.tomcat.clustering.membership-address=228.0.0.4
Multicast address for membership. The multicast address that the membership will broadcast its presence and listen for other heartbeats on. The default value is 228.0.0.4 Make sure your network is enabled for multicast traffic. The multicast address, in conjunction with the port is what creates a cluster group. To divide up your farm into several different group, or to split up QA from production, change the port or the address |
cas.server.tomcat.clustering.membership-drop-time=3000
The membership component will time out members and notify the Channel if a member fails to send a heartbeat within a give time. The default value is 3000 ms. This means, that if a heartbeat is not received from a member in that timeframe, the membership component will notify the cluster of this. On a high latency network you may wish to increase this value, to protect against false positives. Apache Tribes also provides a TcpFailureDetector that will verify a timeout using a TCP connection when a heartbeat timeout has occurred. This protects against false positives. |
cas.server.tomcat.clustering.membership-frequency=500
The frequency in milliseconds in which heartbeats are sent out. The default value is 500 ms. In most cases the default value is sufficient. Changing this value, changes the interval in between heartbeats. |
cas.server.tomcat.clustering.membership-local-loopback-disabled=false
Membership uses multicast, it will call java.net.MulticastSocket.setLoopbackMode(localLoopbackDisabled). When localLoopbackDisabled==true multicast messages will not reach other nodes on the same local machine. The default is false. |
cas.server.tomcat.clustering.membership-port=45564
Multicast port (the port and the address together determine cluster membership. The multicast port, the default value is 45564 The multicast port, in conjunction with the address is what creates a cluster group. To divide up your farm into several different group, or to split up QA from production, change the port or the address |
cas.server.tomcat.clustering.membership-recovery-counter=10
Membership uses multicast, it will call java.net.MulticastSocket.setLoopbackMode(localLoopbackDisabled). When localLoopbackDisabled==true multicast messages will not reach other nodes on the same local machine. The default is false. |
cas.server.tomcat.clustering.membership-recovery-enabled=true
In case of a network failure, Java multicast socket don't transparently fail over, instead the socket will continuously throw |
cas.server.tomcat.clustering.receiver-address=auto
The address (network interface) to listen for incoming traffic. |
cas.server.tomcat.clustering.receiver-auto-bind=100
Default value is 100. Use this value if you wish to automatically avoid port conflicts the cluster receiver will try to open a server socket on the port attribute port, and then work up autoBind number of times. |
cas.server.tomcat.clustering.receiver-max-threads=6
Maximum threads configured for the listener. The maximum number of threads in the receiver thread pool. The default value is 6 Adjust this value relative to the number of nodes in the cluster, the number of messages being exchanged and the hardware you are running on. A higher value doesn't mean more efficiency, tune this value according to your own test results. |
cas.server.tomcat.clustering.receiver-port=4000
The listen port for incoming data. The default value is |
cas.server.tomcat.clustering.receiver-timeout=5000
Listener timeout. The value in milliseconds for the polling timeout in the NioReceiver. On older versions of the JDK there have been bugs, that should all now be cleared out where the selector never woke up. The default value is a very high 5000 milliseconds. |
If you need to design your own password encoding scheme where the type is specified as a fully qualified Java class name, the structure of the class would be similar to the following:
1
2
3
4
5
6
7
8
9
10
11
package org.example.cas;
import org.springframework.security.crypto.codec.*;
import org.springframework.security.crypto.password.*;
public class MyEncoder extends AbstractPasswordEncoder {
@Override
protected byte[] encode(CharSequence rawPassword, byte[] salt) {
return ...
}
}
If you need to design your own password encoding scheme where the type is specified as a path to a Groovy script, the structure of the script would be similar to the following:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import java.util.*
byte[] run(final Object... args) {
def rawPassword = args[0]
def generatedSalt = args[1]
def logger = args[2]
def casApplicationContext = args[3]
logger.debug("Encoding password...")
return ...
}
Boolean matches(final Object... args) {
def rawPassword = args[0]
def encodedPassword = args[1]
def logger = args[2]
def casApplicationContext = args[3]
logger.debug("Does match or not ?");
return ...
Password Policy Strategies
If the password policy strategy is to be handed off to a Groovy script, the outline of the script may be as follows:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import java.util.*
import org.ldaptive.auth.*
import org.apereo.cas.*
import org.apereo.cas.authentication.*
import org.apereo.cas.authentication.support.*
List<MessageDescriptor> run(final Object... args) {
def response = args[0]
def configuration = args[1];
def logger = args[2]
def applicationContext = args[3]
logger.info("Handling password policy [{}] via ${configuration.getAccountStateHandler()}", response)
def accountStateHandler = configuration.getAccountStateHandler()
return accountStateHandler.handle(response, configuration)
}
The parameters passed are as follows:
| Parameter | Description |
|---|---|
response |
The LDAP authentication response of type org.ldaptive.auth.AuthenticationResponse |
configuration |
The LDAP password policy configuration carrying the account state handler defined. |
logger |
The object responsible for issuing log messages such as logger.info(...). |
Authentication handlers that generally deal with username-password credentials can be configured to transform the user id prior to executing the authentication sequence. Each authentication strategy in CAS provides settings to properly transform the principal. Refer to the relevant settings for the authentication strategy at hand to learn more.
Authentication handlers as part of principal transformation may also be provided a path to a Groovy script to transform the provided username. The outline of the script may take on the following form:
1
2
3
4
5
String run(final Object... args) {
def providedUsername = args[0]
def logger = args[1]
return providedUsername.concat("SomethingElse")
}
Configuration Metadata
The collection of configuration properties listed in this section are automatically generated from the CAS source and components that contain the actual field definitions, types, descriptions, modules, etc. This metadata may not always be 100% accurate, or could be lacking details and sufficient explanations.
Be Selective
This section is meant as a guide only. Do NOT copy/paste the entire collection of settings into your CAS configuration; rather pick only the properties that you need. Do NOT enable settings unless you are certain of their purpose and do NOT copy settings into your configuration only to keep them as reference. All these ideas lead to upgrade headaches, maintenance nightmares and premature aging.
YAGNI
Note that for nearly ALL use cases, declaring and configuring properties listed here is sufficient. You should NOT have to explicitly massage a CAS XML/Java/etc configuration file to design an authentication handler, create attribute release policies, etc. CAS at runtime will auto-configure all required changes for you. If you are unsure about the meaning of a given CAS setting, do NOT turn it on without hesitation. Review the codebase or better yet, ask questions to clarify the intended behavior.
Naming Convention
Property names can be specified in very relaxed terms. For instance cas.someProperty, cas.some-property, cas.some_property are all valid names. While all
forms are accepted by CAS, there are certain components (in CAS and other frameworks used) whose activation at runtime is conditional on a property value, where
this property is required to have been specified in CAS configuration using kebab case. This is both true for properties that are owned by CAS as well as those
that might be presented to the system via an external library or framework such as Spring Boot, etc.
When possible, properties should be stored in lower-case kebab format, such as cas.property-name=value.
The only possible exception to this rule is when naming actuator endpoints; The name of the
actuator endpoints (i.e. ssoSessions) MUST remain in camelCase mode.
Settings and properties that are controlled by the CAS platform directly always begin with the prefix cas. All other settings are controlled and provided
to CAS via other underlying frameworks and may have their own schemas and syntax. BE CAREFUL with
the distinction. Unrecognized properties are rejected by CAS and/or frameworks upon which CAS depends. This means if you somehow misspell a property definition
or fail to adhere to the dot-notation syntax and such, your setting is entirely refused by CAS and likely the feature it controls will never be activated in the
way you intend.
Validation
Configuration properties are automatically validated on CAS startup to report issues with configuration binding, specially if defined CAS settings cannot be
recognized or validated by the configuration schema. The validation process is on by default and can be skipped on startup using a special system
property SKIP_CONFIG_VALIDATION that should be set to true. Additional validation processes are also handled
via Configuration Metadata and property migrations applied automatically on
startup by Spring Boot and family.
Indexed Settings
CAS settings able to accept multiple values are typically documented with an index, such as cas.some.setting[0]=value. The index [0] is meant to be
incremented by the adopter to allow for distinct multiple configuration blocks.